<?php

namespace App\Admin\Repositories\Statistics;

use App\Admin\Controllers\AdminController;
use App\Enums\DataPermission;
use App\Enums\SalePerformanceSaleType;
use App\Enums\SaleSource;
use App\Enums\SalePerformanceType;
use App\Enums\SaleTrack;
use App\Models\Sale;
use App\Models\SalePerformance;
use App\Models\SalePerformanceLog;
use App\Models\User;
use Dcat\Admin\Repositories\Repository;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Dcat\Admin\Grid;

class SalePersonalRepository extends Repository
{
    /**
     * 排序字段
     * @var string
     */
    public mixed $order_column;

    /**
     * 排序方式
     * @var string
     */
    public mixed $order_type;


    public function get(Grid\Model $model): array
    {
        [$orderColumn, $orderType] = $model->getSort();
        $this->order_column = $orderColumn ?: 'date_time';
        $this->order_type = $orderType ?: 'desc';
        $date_start = $model->filter()->input('date.start', '');
        $date_end = $model->filter()->input('date.end', '');
        $username = $model->filter()->input('username', '');
        //部门
        $dep_id = $model->filter()->input('dept_id', '');


        //接入,添加,流失
        $type = request('type', 'day');
        if ($type == 'month') {
            $date_start = $date_start ? date('Y-m', strtotime($date_start . '-01')) : date('Y-m');//默认本年
            $date_end = $date_end ? date('Y-m', strtotime($date_end . '-01')) : $date_start;
            list($sale_query, $performance_query, $performance_log_query) = $this->query('%Y-%m');
        } else {
            $date_start = $date_start ? date('Y-m-d', strtotime($date_start)) : date('Y-m-d');//默认当天
            $date_end = $date_end ? date('Y-m-d', strtotime($date_end)) : $date_start;
            list($sale_query, $performance_query, $performance_log_query) = $this->query('%Y-%m-%d');
        }
        $performance_log = $performance_log_query
            ->when($type == 'month', function ($query) use ($date_start, $date_end) {
                $query->whereBetween('created_at', [Carbon::parse($date_start)->startOfMonth(), Carbon::parse($date_end)->endOfMonth()]);
            }, function (Builder $query) use ($date_start, $date_end) {
                $query->whereBetween('created_at', [Carbon::parse($date_start)->startOfDay(), Carbon::parse($date_end)->endOfDay()]);
            })
            ->when($username, function (Builder $builder) use ($username) {
                $builder->whereHas('user', function ($query) use ($username) {
                    $query->where('name', 'like', '%' . $username . '%');
                });

            })
            ->when($dep_id, function (Builder $builder) use ($dep_id) {
                $builder->whereHas('user', function ($query) use ($dep_id) {
                    $query->where('dept_id', '=', $dep_id);
                });
            })
            ->get()->toArray();


        $performance = $performance_query
            ->when($type == 'month', function ($query) use ($date_start, $date_end) {
                $query->whereBetween('created_at', [Carbon::parse($date_start)->startOfMonth(), Carbon::parse($date_end)->endOfMonth()]);
            }, function (Builder $query) use ($date_start, $date_end) {
                $query->whereBetween('created_at', [Carbon::parse($date_start)->startOfDay(), Carbon::parse($date_end)->endOfDay()]);
            })
            ->when($username, function (Builder $builder) use ($username) {
                $builder->whereHas('user', function ($query) use ($username) {
                    $query->where('name', 'like', '%' . $username . '%');
                });

            })
            ->when($dep_id, function (Builder $builder) use ($dep_id) {
                $builder->whereHas('user', function ($query) use ($dep_id) {
                    $query->where('dept_id', '=', $dep_id);
                });
            })
            ->get()->toArray();


        $sale = $sale_query
            ->when($type == 'month', function ($query) use ($date_start, $date_end) {
                $query->whereBetween('created_at', [Carbon::parse($date_start)->startOfMonth(), Carbon::parse($date_end)->endOfMonth()]);
            }, function ($query) use ($date_start, $date_end) {
                $query->whereBetween('created_at', [Carbon::parse($date_start)->startOfDay(), Carbon::parse($date_end)->endOfDay()]);
            })
            ->when($username, function (Builder $builder) use ($username) {
                $builder->whereHas('user', function ($query) use ($username) {
                    $query->where('name', 'like', '%' . $username . '%');
                });
            })
            ->when($dep_id, function (Builder $builder) use ($dep_id) {
                $builder->whereHas('user', function ($query) use ($dep_id) {
                    $query->where('dept_id', '=', $dep_id);
                });
            })
            ->get()
            ->toArray();
        if ($type == 'month') {
            //按月
            $all_date = [];
            for ($month = Carbon::parse($date_start)->startOfMonth(); $month <= Carbon::parse($date_end)->endOfMonth(); $month->addMonth()) {
                $all_date[] = $month->format('Y-m');
            }
        } else {
            //按天
            $all_days = Carbon::parse($date_start)->range(Carbon::parse($date_end));
            $all_date = [];
            foreach ($all_days as $item) {
                $all_date[] = $item->format('Y-m-d');
            }
        }
        return $this->merge($sale, $performance, $performance_log, $all_date);

    }


    //获取查询对象
    private function query(string $time_format): array
    {
        $data_permission = app(AdminController::class)->getAdminDataPermission();
        $user = AdminController::getUserInfo();
        $sale = Sale::query()->with('user:id,name')
            ->where('source', '!=', SaleSource::OPEN)
            ->when($data_permission == DataPermission::SELF, function (Builder $builder) use ($user) {
                $builder->where('user_id', '=', $user->id);
            })
            ->when($data_permission == DataPermission::DEPARTMENT, function (Builder $builder) use ($user) {
                //部门数据
                $builder->whereHas('user', function (Builder $query) use ($user) {
                    $query->where('ding_id', $user->ding_id)
                        ->where('dept_id', $user->dept_id);
                });
            })
            ->when($data_permission == DataPermission::BRAND, function (Builder $builder) use ($user) {
                //品牌资质数据
                $builder->whereHas('customer', function (Builder $query) use ($user) {
                    $query->where('brand_option_id', '=', $user->brand_option_id ?? 0);
                });
            })
            ->selectRaw("
            DATE_FORMAT( created_at, '$time_format' ) date_time,user_id,
            COUNT(  id ) count_enter,
            COUNT(CASE WHEN deal = 1 THEN 1 END) count_sale,
            COUNT( CASE WHEN track = " . SaleTrack::ADDED . " THEN 1 END ) count_reception,
            COUNT( CASE WHEN track <> " . SaleTrack::ADDED . " THEN 1 END ) count_loss
        ")->groupBy(['date_time', 'user_id']);

        $performance = SalePerformance::query()
            ->where('sale_type', SalePerformanceSaleType::SALE)
            ->when($data_permission == DataPermission::SELF, function (Builder $builder) use ($user) {
                $builder->where('user_id', '=', $user->id);
            })
            ->when($data_permission == DataPermission::DEPARTMENT, function (Builder $builder) use ($user) {
                //部门数据
                $builder->whereHas('user', function (Builder $query) use ($user) {
                    $query->where('ding_id', $user->ding_id)
                        ->where('dept_id', $user->dept_id);
                });
            })
            ->when($data_permission == DataPermission::BRAND, function (Builder $builder) use ($user) {
                //品牌资质数据
                $builder->whereHas('customer', function (Builder $query) use ($user) {
                    $query->where('brand_option_id', '=', $user->brand_option_id ?? 0);
                });
            })
            ->selectRaw("
            DATE_FORMAT( created_at, '$time_format' ) date_time,user_id,
            COUNT( CASE WHEN (deposit > 0 AND balance > 0)  OR (deposit = 0 AND money > 0) THEN 1 END ) count_full_payment,
            COUNT( CASE WHEN deposit = 0 AND money > 0 THEN 1 END ) count_no_deposit,
            COUNT( CASE WHEN deposit > 0 AND balance > 0 THEN 1 END ) count_deposit,
            COUNT( CASE WHEN timely = 1 THEN 1 END ) count_sale_timely,
            SUM( money ) money_total,
            SUM( arrears ) arrears_total,
            SUM( balance ) cash_back_total
        ")->groupBy(['date_time', 'user_id']);

        $performance_log = SalePerformanceLog::query()
            ->whereHas('salePerformance', function (Builder $builder) {
                $builder->where('sale_type', SalePerformanceSaleType::SALE);
            })
            ->when($data_permission == DataPermission::SELF, function (Builder $builder) use ($user) {
                $builder->where('user_id', '=', $user->id);
            })
            ->when($data_permission == DataPermission::DEPARTMENT, function (Builder $builder) use ($user) {
                //部门数据
                $builder->whereHas('user', function (Builder $query) use ($user) {
                    $query->where('ding_id', $user->ding_id)
                        ->where('dept_id', $user->dept_id);
                });
            })
            ->when($data_permission == DataPermission::BRAND, function (Builder $builder) use ($user) {
                //品牌资质数据
                $builder->whereHas('salePerformance.customer', function (Builder $query) use ($user) {
                    $query->where('brand_option_id', '=', $user->brand_option_id ?? 0);
                });
            })
            ->selectRaw("
            DATE_FORMAT( created_at, '$time_format' ) date_time,user_id,
            SUM( money ) money_total
        ")->groupBy(['date_time', 'user_id']);

        return [$sale, $performance, $performance_log];
    }


    public static function getModelSum($models): ?array
    {
        if (!empty($models)) {
            $total = ['date_time' => '总计', 'user_id' => 0, 'user_name' => ''];
            $keys = array_keys(Arr::first($models));

            foreach ($keys as $key) {
                if (in_array($key, ['date_time', 'user_id', 'user_name'])) {
                    continue;
                }
                $total[$key] = array_sum(array_column($models, $key));
            }
            $total['money_total'] = intval($total['money_total']);
            $total['arrears_total'] = intval($total['arrears_total']);
            $total['cash_back_total'] = intval($total['cash_back_total']);
            return $total;
        }

        return null;
    }


    public function merge($sale, $performance, $performance_log, $all_date): array
    {
        $models = [];

        $all_user_id = array_merge(array_column($sale, 'user_id'), array_column($performance, 'user_id'), array_column($performance_log, 'user_id'));
        foreach ($all_user_id as $user_id) {
            foreach ($all_date as $date) {
                if (!collect($sale)->where('user_id', $user_id)->where('date_time', $date)->count()) {
                    $item_data['date_time'] = $date;
                    $item_data['user_id'] = $user_id;
                    $item_data['user'] = User::query()->where('id', $user_id)->select(['id', 'name'])->first();

                    $item_data['count_enter'] = 0;
                    $item_data['count_sale'] = 0;
                    $item_data['count_reception'] = 0;
                    $item_data['count_loss'] = 0;
                    $item_data['dispute_money'] = 0;
                    $item_data['dispute_money_unit'] = 0;
                    $item_data['count_full_payment'] = 0;
                    $item_data['count_no_deposit'] = 0;
                    $item_data['count_deposit'] = 0;
                    $item_data['count_sale_timely'] = 0;
                    $item_data['money_total'] = 0;
                    $item_data['arrears_total'] = 0;
                    $item_data['cash_back_total'] = 0;

                    $sale[] = $item_data;
                }
            }
        }


        foreach ($sale as $k1 => $v1) {
            if (!isset($v1['user']['name'])) {
                continue;
            }
            $models[$k1]['date_time'] = $v1['date_time'];
            $models[$k1]['user_id'] = $v1['user_id'];
            $models[$k1]['user_name'] = $v1['user']['name'];
            $models[$k1]['count_enter'] = $v1['count_enter'];
            $models[$k1]['count_sale'] = $v1['count_sale'];
            $models[$k1]['count_reception'] = $v1['count_reception'];
            $models[$k1]['count_loss'] = $v1['count_loss'];
            $models[$k1]['dispute_money'] = $v1['dispute_money'] ?? 0;
            $models[$k1]['dispute_money_unit'] = 0;
            $models[$k1]['count_full_payment'] = 0;
            $models[$k1]['count_no_deposit'] = 0;
            $models[$k1]['count_deposit'] = 0;
            $models[$k1]['count_sale_timely'] = 0;
            $models[$k1]['money_total'] = 0;
            $models[$k1]['arrears_total'] = 0;
            $models[$k1]['cash_back_total'] = 0;
            foreach ($performance as $v2) {
                if ($v2['date_time'] == $v1['date_time'] && $v2['user_id'] == $v1['user_id']) {

                    $models[$k1]['date_time'] = $v1['date_time'];
                    //$models[$k1]['count_sale'] = isset($models[$k1]['count_sale']) ? $models[$k1]['count_sale'] + $v2['count_sale'] : $v2['count_sale'];
                    $models[$k1]['count_full_payment'] = isset($models[$k1]['count_full_payment']) ? $models[$k1]['count_full_payment'] + $v2['count_full_payment'] : $v2['count_full_payment'];
                    $models[$k1]['count_no_deposit'] = isset($models[$k1]['count_no_deposit']) ? $models[$k1]['count_no_deposit'] + $v2['count_no_deposit'] : $v2['count_no_deposit'];
                    $models[$k1]['count_deposit'] = isset($models[$k1]['count_deposit']) ? $models[$k1]['count_deposit'] + $v2['count_deposit'] : $v2['count_deposit'];
                    $models[$k1]['count_sale_timely'] = isset($models[$k1]['count_sale_timely']) ? $models[$k1]['count_sale_timely'] + $v2['count_sale_timely'] : $v2['count_sale_timely'];
                    //$models[$k1]['money_total'] = isset($models[$k1]['money_total']) ? $models[$k1]['money_total'] + $v2['money_total'] : $v2['money_total'];
                    $models[$k1]['arrears_total'] = isset($models[$k1]['arrears_total']) ? $models[$k1]['arrears_total'] + $v2['arrears_total'] : $v2['arrears_total'];
                    $models[$k1]['cash_back_total'] = isset($models[$k1]['cash_back_total']) ? $models[$k1]['cash_back_total'] + $v2['cash_back_total'] : $v2['cash_back_total'];
                }
            }

            foreach ($performance_log as $item) {
                if ($item['date_time'] == $v1['date_time'] && $item['user_id'] == $v1['user_id']) {
                    $models[$k1]['money_total'] = $item['money_total'];
                }
            }
        }

        $modelSum = self::getModelSum($models);

        if (count($models)) {
            array_walk($models, function (&$model) {
                SaleRepository::commonModelArrayWalkCallback($model);
            });
            if ($this->order_type && $this->order_column) {
                $models = orderSort($this->order_type, $this->order_column, $models);
            }
            SaleRepository::commonModelArrayWalkCallback($modelSum);
            $models[] = $modelSum;
            return $models;
        }
        return [];
    }
}
